package rpc

import (
	"context"
	upbv1 "jmicro/api/user/v1"
	"jmicro/app/jshop/api/internal/data"
	data2 "jmicro/app/jshop/api/internal/domain/do"
	"jmicro/app/pkg/code"
	"jmicro/app/pkg/gorm"
	"jmicro/jmicro/registry"
	"jmicro/jmicro/server/rpcserver"
	"jmicro/jmicro/server/rpcserver/clientinterceptors"
	metav1 "jmicro/pkg/common/meta/v1"
	itime "jmicro/pkg/common/time"
	"jmicro/pkg/errors"
	"time"
)

const userServiceName = "discovery:///jmicro-user-srv"

type users struct {
	uc upbv1.UserClient
}

func (u *users) List(ctx context.Context, orderby []string, pages metav1.ListMeta) (*data2.UserListDO, error) {
	list, err := u.uc.GetUserList(ctx, &upbv1.PageInfo{
		Pn:    uint32(pages.Page),
		PSize: uint32(pages.PageSize),
	})
	if err != nil {
		return nil, err
	}
	userlist := &data2.UserListDO{TotalCount: int64(list.Total)}
	for _, item := range list.Data {
		userlist.Items = append(userlist.Items, &data2.UserDO{
			BaseModel: gorm.BaseModel{ID: item.Id},
			Mobile:    item.Mobile,
			NickName:  item.NickName,
			Birthday:  itime.Time{time.Unix(int64(item.BirthDay), 0)},
			Gender:    item.Gender,
			Role:      item.Role,
		})
	}
	return userlist, nil
}

func NewUserServiceClient(r registry.Discovery) (upbv1.UserClient, error) {
	conn, err := rpcserver.DialInsecure(
		context.Background(),
		rpcserver.WithEndpoint(userServiceName),
		rpcserver.WithDiscovery(r),
		rpcserver.WithClientUnaryInterceptor(clientinterceptors.UnaryTracingInterceptor),
	)
	if err != nil {
		return nil, err
	}
	c := upbv1.NewUserClient(conn)
	return c, nil
}
func NewUsers(uc upbv1.UserClient) data.UserData {
	return &users{uc}
}
func (u *users) Create(ctx context.Context, user *data2.UserDO) error {
	protoUser := &upbv1.CreateUserInfo{
		NickName: user.NickName,
		PassWord: user.PassWord,
		Mobile:   user.Mobile,
	}
	userRsp, err := u.uc.CreateUser(ctx, protoUser)
	if err != nil {
		return err
	}
	user.ID = userRsp.Id
	return err
}

func (u *users) Update(ctx context.Context, user *data2.UserDO) error {
	protoUser := &upbv1.UpdateUserInfo{
		Id:       user.ID,
		NickName: user.NickName,
		Gender:   user.Gender,
		BirthDay: uint64(user.Birthday.Unix()),
	}
	_, err := u.uc.UpdateUser(ctx, protoUser)
	if err != nil {
		return err
	}
	return nil
}

func (u *users) Get(ctx context.Context, userID uint64) (*data2.UserDO, error) {
	user, err := u.uc.GetUserById(ctx, &upbv1.IdRequest{Id: int32(userID)})
	if err != nil {
		return nil, err
	}
	return &data2.UserDO{
		BaseModel: gorm.BaseModel{ID: user.Id},
		Mobile:    user.Mobile,
		NickName:  user.NickName,
		Birthday:  itime.Time{time.Unix(int64(user.BirthDay), 0)},
		Gender:    user.Gender,
		Role:      user.Role,
		PassWord:  user.PassWord,
	}, nil
}

func (u *users) GetByMobile(ctx context.Context, mobile string) (*data2.UserDO, error) {
	user, err := u.uc.GetUserByMobile(ctx, &upbv1.MobileRequest{Mobile: mobile})
	if err != nil {
		return nil, err
	}
	return &data2.UserDO{
		BaseModel: gorm.BaseModel{ID: user.Id},
		Mobile:    user.Mobile,
		NickName:  user.NickName,
		Birthday:  itime.Time{time.Unix(int64(user.BirthDay), 0)},
		Gender:    user.Gender,
		Role:      user.Role,
		PassWord:  user.PassWord,
	}, nil
}

func (u *users) CheckPassWord(ctx context.Context, password, encryptedPwd string) error {
	cres, err := u.uc.CheckPassWord(ctx, &upbv1.PasswordCheckInfo{
		Password:          password,
		EncryptedPassword: encryptedPwd,
	})
	if err != nil {
		return err
	}
	if cres.Success {
		return nil
	}
	return errors.WithCode(code.ErrUserPasswordIncorrect, "密码错误")
}

var _ data.UserData = &users{}
